package com.gongguizhijia.Util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.gongguizhijia.Constants.Constants;
import com.gongguizhijia.pojo.*;
import org.apache.commons.lang3.StringUtils;

import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chj
 * @date 2021/6/10 10:08
 */
public class ExportExcel {

    /**
     * 解放专检
     *
     * @param map
     * @param fileName
     */
    public static void ExportJfExcel(Map<String, List> map, String fileName) {

        //获取桌面路径
        File desktopDir = FileSystemView.getFileSystemView().getHomeDirectory();
        String desktopPath = desktopDir.getAbsolutePath();

        //获取system_id
        String systemId = null;
        List<SystemMapMdb> systemMapMdbList = map.get(Constants.SYSTEM_MAP_MDB);
        for (SystemMapMdb systemMapMdb : systemMapMdbList) {
            if (StringUtils.isNotBlank(systemMapMdb.getDll_name())) {
                String dllName = systemMapMdb.getDll_name().substring(0, systemMapMdb.getDll_name().length() - 4) + ".mdb";
                if (dllName.equals(fileName)) {
                    systemId = systemMapMdb.getSystem_id();
                }
            }
        }

        //文件名称
        /*+ fileName.substring(0, fileName.length() - 4) */
        String newFileName = desktopPath + "\\test2\\" + systemId + "-协议占位符" + ".xlsx";

        //获取Excel输出流
        ExcelWriter excelWriter = ExcelWriterUtil.getExcelWriter(newFileName);

        //数据
        //获取基本信息概览数据
        List<List<Object>> systemInfo = getSystemInfo(map, fileName);
        //获取进系统命令数据
        List<List<Object>> systemCommand = getSystemCommand();
        //获取故障码命令数据
        List<List<Object>> failCodeCommand = getFailCodeCommand();
        //获取故障码描述数据
        List<FaultCodeDescModel> failCodeDesc = getFailCodeDesc(map, fileName);
        //获取数据流数据
        List<DataStreamModel> dataStream = getDataStream(map, fileName);
        //获取故版本信息数据
        List<VersionInfoModel> versionInfo = getVersionInfo(map, fileName);

        //表单
        //基本信息概览
        WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "基本信息概览").build();
        excelWriter.write(systemInfo, writeSheet1);

        //进系统命令
        WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "进系统命令").build();
        excelWriter.write(systemCommand, writeSheet2);

        //故障码命令
        WriteSheet writeSheet3 = EasyExcel.writerSheet(3, "故障码命令").build();
        excelWriter.write(failCodeCommand, writeSheet3);

        //故障码描述
        WriteSheet writeSheet4 = EasyExcel.writerSheet(4, "故障码描述").head(FaultCodeDescModel.class).build();
        if (!failCodeDesc.isEmpty()) {
            excelWriter.write(failCodeDesc, writeSheet4);
        }

        //数据流
        WriteSheet writeSheet5 = EasyExcel.writerSheet(5, "数据流").head(DataStreamModel.class).build();
        if (!dataStream.isEmpty()) {
            excelWriter.write(dataStream, writeSheet5);
        }

        //版本信息
        WriteSheet writeSheet6 = EasyExcel.writerSheet(6, "版本信息").head(VersionInfoModel.class).build();
        if (!versionInfo.isEmpty()) {
            excelWriter.write(versionInfo, writeSheet6);
        }

        excelWriter.finish();
    }

    /**
     * 版本信息
     *
     * @param map
     * @param fileName
     * @return
     */
    public static List<VersionInfoModel> getVersionInfo(Map<String, List> map, String fileName) {

        //获取数据
        List<ECU> ecuLists = map.get(Constants.ECU);
        List<EcuInfoParseConfig> configLists = map.get(Constants.ECU_INFO_PARSE_CONFIG);

        //取出需要处理的数据
        List<ECU> ecuList = new ArrayList<>();
        for (ECU list : ecuLists) {
            if (fileName.equals(list.getFileName())) {
                ecuList.add(list);
            }
        }
        List<EcuInfoParseConfig> configList = new ArrayList<>();
        for (EcuInfoParseConfig list : configLists) {
            if (fileName.equals(list.getFileName())) {
                configList.add(list);
            }
        }

        //返回结果集构建
        List<VersionInfoModel> result = new ArrayList<>();
        //填充结果集数据
        for (ECU ecu : ecuList) {
            result.add(ExcelWriterUtil.getVersionInfoModel1(ecu));
        }

        for (EcuInfoParseConfig ecuInfoParseConfig : configList) {
            result.add(ExcelWriterUtil.getVersionInfoModel2(ecuInfoParseConfig));
        }
        //返回结果
        return result;
    }

    /**
     * 数据流
     *
     * @param map
     * @param fileName
     * @return
     */
    public static List<DataStreamModel> getDataStream(Map<String, List> map, String fileName) {
        //获取数据
        List<DataFlow> listDataFlow = map.get(Constants.DATA_FLOW);
        List<EcuDataFlowConfig> listEcuDataFlowConfig = map.get(Constants.ECU_DATA_FLOW_CONFIG);

        //数据处理 取出需要的数据
//        List<DataFlow> dataFlows = new ArrayList<>();
//        for (DataFlow dataFlow : listDataFlow) {
//            if (fileName.equals(dataFlow.getFileName())) {
//                dataFlows.add(dataFlow);
//            }
//        }

        //数据处理 取出需要的数据
        List<DataFlow> dataFlows = listDataFlow.stream()
                .filter(dataFlow -> fileName.equals(dataFlow.getFileName()))
                .collect(Collectors.toList());

        List<EcuDataFlowConfig> ecuDataFlowConfigs = listEcuDataFlowConfig.stream()
                .filter(ecuDataFlowConfig -> fileName.equals(ecuDataFlowConfig.getFileName()))
                .collect(Collectors.toList());

        List<DataStreamModel> dataStreamModels = new ArrayList<>();

        //DataFlow
        for (DataFlow dataFlow : dataFlows) {
            DataStreamModel dataStreamModel = new DataStreamModel();

            if (StringUtils.isNotBlank(dataFlow.getPid())) {
                dataStreamModel.setOrder(Utils.getFileAddSpace(dataFlow.getPid()));
                dataStreamModel.setKvId("");
                if (StringUtils.isNotBlank(dataFlow.getLang0())) {
                    dataStreamModel.setDesc(dataFlow.getLang0());
                } else {
                    dataStreamModel.setDesc(dataFlow.getParaName());
                }
                dataStreamModel.setUnit(dataFlow.getUnit());
                dataStreamModel.setIsShow("是");
                dataStreamModel.setRemark("解放");
                dataStreamModel.setDigit("2");
                //获取type类型
                String type = null;
                if (dataFlow.getValueType() != null) {
                    type = dataFlow.getValueType();
                } else {
                    type = dataFlow.getParseType();
                }
                //获取 系数 以及偏移量
                //偏移量
                String offset = dataFlow.getIb();
                //系数
                String iaz = dataFlow.getIaz();
                double iazLong = 0;
                if (iaz != null) {
                    iazLong = Double.parseDouble(iaz);
                }
                String iam = dataFlow.getIam();
                double iamLong = 0;
                if (iam != null) {
                    iamLong = Double.parseDouble(iam);
                }
                String ia = dataFlow.getIa();
                double iaLong = 0;
                if (ia != null) {
                    if (ia.startsWith(".")) {
                        ia = "0" + ia;
                        iaLong = Double.parseDouble(ia);
                    }
                    if (ia.contains("/")) {
                        String[] split = ia.split("/");
                        iaLong = Double.parseDouble(split[0]) / Double.parseDouble(split[1]);
                    }
                }
                double coefficient = 0;
                if (ia != null) {
                    coefficient = iaLong;
                } else {
                    if (iaz != null && iam != null) {
                        coefficient = iazLong / iamLong;
                    }
                }
                String coefficientStr = coefficient + "";
                //获取 起始位 和 长度
                //表格中数据 需要 /8 进行处理
                String startPlaceStr = null;
                //表格中数据 不需要处理
                String dataLengthStr = null;
                if (StringUtils.isNotBlank(dataFlow.getStartIndex()) && StringUtils.isNotBlank(dataFlow.getDataLength())) {
                    startPlaceStr = Utils.subNumberText(dataFlow.getStartIndex());
                    dataLengthStr = Utils.subNumberText(dataFlow.getDataLength());


                } else {
                    //需要 /8 进行处理
                    startPlaceStr = Utils.subNumberText(dataFlow.getBitStart());
                    //需要 /8 进行处理
                    dataLengthStr = Utils.subNumberText(dataFlow.getBitLength());


                }
                //转换类型
                Integer startPalace = Integer.valueOf(startPlaceStr);
                Integer dataLength = Integer.parseInt(dataLengthStr) * 8;

                //针对 类型 6 或者 7  有无符号 浮点型
                if ("6".equals(type) || "7".equals(type)) {
                    //解析方式
                    dataStreamModel.setDecode("RD022");
                    //解析公式
                    String formulaByRD022 = ArkProtocolRules.getFormulaByRD022(startPalace, dataLength, dataStreamModel.getOrder());
                    dataStreamModel.setAnalyticFormula(formulaByRD022);
                } else if ("3".equals(type)) {
                    //解析方式
                    dataStreamModel.setDecode("RK001");
                    String formulaByRK001 = ArkProtocolRules.getFormulaByRK001(startPalace, dataLength, dataStreamModel.getOrder());
                    //解析公式
                    dataStreamModel.setAnalyticFormula(formulaByRK001);
                } else if ("4".equals(type)) {
                    //解析方式
                    dataStreamModel.setDecode("RD009");
                    String formulaByRD009 = ArkProtocolRules.getFormulaByRD009(startPalace, dataLength, dataStreamModel.getOrder(), coefficientStr, offset);
                    //解析公式
                    dataStreamModel.setAnalyticFormula(formulaByRD009);
                } else if ("5".equals(type)) {
                    //解析方式
                    dataStreamModel.setDecode("RD001");
                    String formulaByRD001 = ArkProtocolRules.getFormulaByRD001(startPalace, dataLength, dataStreamModel.getOrder(), coefficientStr, offset);
                    //解析公式
                    dataStreamModel.setAnalyticFormula(formulaByRD001);
                } else if ("8".equals(type)) {
                    //解析方式
                    dataStreamModel.setDecode("RD008");
                    String formulaByRD008 = ArkProtocolRules.getFormulaByRD008(startPalace, dataLength, dataStreamModel.getOrder(), coefficientStr, offset);
                    //解析公式
                    dataStreamModel.setAnalyticFormula(formulaByRD008);
                } else if (type == null) {
                    //解析方式
                    dataStreamModel.setDecode("数据源为空");
                    //解析公式
                    dataStreamModel.setAnalyticFormula("数据源为空,无法获取");
                } else {
                    //解析方式
                    dataStreamModel.setDecode("暂无对应协议规则" + type);
                    String result = ArkProtocolRules.getForOtherProtocol(startPalace, dataLength, dataStreamModel.getOrder());
                    //解析公式
                    dataStreamModel.setAnalyticFormula("取位结果：" + result);
                }
            }
            dataStreamModels.add(dataStreamModel);
        }

        //EcuDataFlowConfig
        for (EcuDataFlowConfig ecuDataFlowConfig : ecuDataFlowConfigs) {
            DataStreamModel dataStreamModel = new DataStreamModel();

            String first = StringUtils.isBlank(ecuDataFlowConfig.getPidFirst()) ? "" : ecuDataFlowConfig.getPidFirst();
            String second = StringUtils.isBlank(ecuDataFlowConfig.getPidSecond()) ? "" : ecuDataFlowConfig.getPidSecond();
            if ("".equals(first) && "".equals(second)) {
            }
            dataStreamModel.setOrder(Utils.getFileAddSpace(first + second));
            dataStreamModel.setKvId("");
            if (StringUtils.isNotBlank(ecuDataFlowConfig.getLang0())) {
                dataStreamModel.setDesc(ecuDataFlowConfig.getLang0());
            } else {
                dataStreamModel.setDesc(ecuDataFlowConfig.getParaName());
            }

            dataStreamModel.setUnit(ecuDataFlowConfig.getUnit());
            dataStreamModel.setIsShow("是");
            dataStreamModel.setRemark("解放");
            dataStreamModel.setDigit("2");


            //获取type类型
            String parseType = ecuDataFlowConfig.getParseType();
            //获取 起始位 和 长度
            String startIndex = Utils.subNumberText(ecuDataFlowConfig.getStartIndex());
            String dataLength = Utils.subNumberText(ecuDataFlowConfig.getDataLength());
            int startIndexInt = 0;
            int dataLengthInt = 0;
            if (StringUtils.isNotBlank(startIndex)) {
                startIndexInt = (int) Double.parseDouble(startIndex);
            }
            if (StringUtils.isNotBlank(dataLength)) {
                dataLengthInt = Integer.parseInt(dataLength) * 8;
            }
            if (parseType == null) {
                //解析方式
                dataStreamModel.setDecode("数据源为空");
                //解析公式
                dataStreamModel.setAnalyticFormula("数据源为空");
            } else if ("4".equals(parseType)) {
                //解析方式
                dataStreamModel.setDecode("RK002");
                String formulaByRK002 = ArkProtocolRules.getFormulaByRK002(startIndexInt, dataLengthInt, dataStreamModel.getOrder());
                //解析公式
                dataStreamModel.setAnalyticFormula(formulaByRK002);
            } else if ("5".equals(parseType)) {
                //解析方式
                dataStreamModel.setDecode("RK001");
                String formulaByRK001 = ArkProtocolRules.getFormulaByRK001(startIndexInt, dataLengthInt, dataStreamModel.getOrder());
                //解析公式
                dataStreamModel.setAnalyticFormula(formulaByRK001);
            } else {
                //解析方式
                dataStreamModel.setDecode("暂无对应协议规则" + parseType);
                String result = ArkProtocolRules.getForOtherProtocol(startIndexInt, dataLengthInt, dataStreamModel.getOrder());
                //解析公式
                dataStreamModel.setAnalyticFormula("取位结果：" + result);
            }
            dataStreamModels.add(dataStreamModel);
        }
        return dataStreamModels;
    }

    /**
     * 故障码描述
     *
     * @param map
     * @param fileName
     * @return
     */
    public static List<FaultCodeDescModel> getFailCodeDesc(Map<String, List> map, String fileName) {

        List<DTC> listDtc = map.get(Constants.DTC);

        List<DTC> DTCList = new ArrayList<>();
        for (DTC dtc : listDtc) {
            if (fileName.equals(dtc.getFileName())) {
                DTCList.add(dtc);
            }
        }

        List<FaultCodeDescModel> faultCodeDescModels = new ArrayList<>();
        String eCode;
        String desc = null;
        int l;
        for (DTC dtc : DTCList) {
            //处理pCode
            eCode = dtc.getPcode();
            if (StringUtils.isNotBlank(eCode)) {
                l = eCode.length();
                if (eCode.startsWith("P")) {
                    eCode = eCode.substring(1, l);
                }
                if (eCode.startsWith("C")) {
                    eCode = "4" + eCode.substring(2, l);
                }
                if (eCode.startsWith("B")) {
                    eCode = "8" + eCode.substring(2, l);
                }
                if (eCode.startsWith("U")) {
                    eCode = "C" + eCode.substring(2, l);
                }
            } else {
                eCode = "数据源为空";
            }
            if (StringUtils.isNotBlank(dtc.getLang0())) {
                desc = dtc.getLang0();
            } else if (StringUtils.isNotBlank(dtc.getChDesc())) {
                desc = dtc.getChDesc();
            } else if (StringUtils.isNotBlank(dtc.getDesc())) {
                desc = dtc.getDesc();
            }

            String pCode = "数据源为空";
            if (StringUtils.isNotBlank(dtc.getPcode())) {
                pCode = dtc.getPcode();
            }

            FaultCodeDescModel faultCodeDescModel = FaultCodeDescModel.builder()
                    .ecode(eCode)
                    .pcode(pCode)
                    .desc(desc)
                    .isShow("是")
                    .remark("解放")
                    .build();
            faultCodeDescModels.add(faultCodeDescModel);
        }
        return faultCodeDescModels;
    }

    /**
     * 故障码命令
     *
     * @return
     */
    public static List<List<Object>> getFailCodeCommand() {
        List<List<Object>> result = new ArrayList<>();

        List<Object> list1 = new ArrayList<>();
        list1.add("故障码读取");
        list1.add("命令");
        list1.add("解析类型");
        list1.add("解析公式");
        list1.add("备注");
        result.add(list1);

        List<Object> list2 = new ArrayList<>();
        list2.add("");
        list2.add("");
        list2.add("");
        list2.add("");
        list2.add("");
        result.add(list2);

        List<Object> list3 = new ArrayList<>();
        list3.add("故障码清除");
        list3.add("命令");
        list3.add("备注");
        result.add(list3);

        List<Object> list4 = new ArrayList<>();
        list4.add("");
        list4.add("");
        list4.add("");
        result.add(list4);
        return result;
    }

    /**
     * 进系统命令
     *
     * @return
     */
    public static List<List<Object>> getSystemCommand() {

        //表单处理
        List<List<Object>> result = new ArrayList<>();

        List<Object> list1 = new ArrayList<>();
        list1.add("组序号");
        list1.add("类型");
        result.add(list1);

        List<Object> list2 = new ArrayList<>();
        list2.add("1");
        list2.add("针脚波特率配置");
        list2.add("");
        list2.add("");
        result.add(list2);

        List<Object> list3 = new ArrayList<>();
        list3.add("1");
        list3.add("帧ID");
        list3.add("");
        list3.add("");
        list3.add("");
        result.add(list3);

        List<Object> list4 = new ArrayList<>();
        list4.add("1");
        list4.add("初始化");
        list4.add("");
        result.add(list4);

        List<Object> list5 = new ArrayList<>();
        list5.add("1");
        list5.add("退出");
        list5.add("");
        result.add(list5);

        List<Object> list6 = new ArrayList<>();
        list6.add("1");
        list6.add("通讯保持");
        list6.add("");
        result.add(list6);

        List<Object> list7 = new ArrayList<>();
        list7.add("1");
        list7.add("版本识别");
        list7.add("");
        result.add(list7);

        return result;
    }

    /**
     * 基本信息预览
     *
     * @param map
     * @param fileName
     * @return
     */
    public static List<List<Object>> getSystemInfo(Map<String, List> map, String fileName) {


        List<List<Object>> result = new ArrayList<>();

        //填充单元格
        List<DataStreamModel> dataStream = getDataStream(map, fileName);
        List<VersionInfoModel> versionInfo = getVersionInfo(map, fileName);
        List<FaultCodeDescModel> failCodeDesc = getFailCodeDesc(map, fileName);

        List<Object> list1 = new ArrayList<>();
        list1.add("系统信息");
        list1.add("系统名称占位符");
        result.add(list1);

        if (!versionInfo.isEmpty()) {
            List<Object> list2 = new ArrayList<>();
            list2.add("预读取脚本");
            list2.add("c1");
            list2.add("c2");
            result.add(list2);

            List<Object> list3 = new ArrayList<>();
            list3.add("");
            list3.add("SCRIPI 000022");
            list3.add("9");
            result.add(list3);

            List<Object> list10 = ExcelWriterUtil.getLineOne();
            List<Object> list11 = ExcelWriterUtil.getLineTwo();
            List<Object> list12 = ExcelWriterUtil.getLineThree();

            result.add(list10);
            result.add(list11);
            result.add(list12);

        }

        if (!failCodeDesc.isEmpty()) {
            List<Object> list4 = ExcelWriterUtil.getLineOne();
            List<Object> list5 = ExcelWriterUtil.getLineTwo();
            List<Object> list6 = ExcelWriterUtil.getLineThree();

            result.add(list4);
            result.add(list5);
            result.add(list6);
        }


        if (!dataStream.isEmpty()) {

            List<Object> list7 = ExcelWriterUtil.getLineOne();
            List<Object> list8 = ExcelWriterUtil.getLineTwo();
            List<Object> list9 = ExcelWriterUtil.getLineThree();

            result.add(list7);
            result.add(list8);
            result.add(list9);
        }
        return result;
    }

}
